package com.log.common;

import cn.hutool.json.JSONObject;
import com.log.biz.LogBiz;
import com.log.context.BaseContextHandler;
import com.log.entity.Logs;
import com.log.util.RedisUtil;
import com.log.util.RequestHolder;
import com.log.util.StringUtils;
import com.log.util.ThrowableUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author zwj
 * @date 2021/3/5
 * @description TODO 切面通用方法
 */
@Component
public class AspectCommon {

    ThreadLocal<Long> currentTime = new ThreadLocal<>();

    @Autowired
    private LogBiz logBiz;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * @return
     */
    public String getUsername() {
        try {
            return BaseContextHandler.getUsername();
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * @return
     */
    public Long getUid() {
        try {
            return Long.parseLong(BaseContextHandler.getUserID());
        } catch (Exception e) {
            return 0L;
        }
    }

    /**
     * @return 浏览器类型
     */
    public String getBrowser() {
        try {
            String browser = "";
            String browserName = RequestHolder.getHttpServletRequest().getHeader("User-Agent").toLowerCase();
            if (browserName.indexOf("msie") > 0) {
                browser = "ie";
            }
            if (browserName.indexOf("firefox") > 0) {
                browser = "firefox";
            }
            if (browserName.indexOf("chrome") > 0) {
                browser = "chrome";
            }
            if (browserName.indexOf("opera") > 0) {
                browser = "opera";
            }
            if (browserName.indexOf("gecko") > 0 && browserName.indexOf("rv:11") > 0) {
                browser = "ie11";
            }
            return browser;
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 保存正确的日志信息
     */
    public void saveINFOLog(ProceedingJoinPoint joinPoint) {
        currentTime.set(System.currentTimeMillis());
        Logs log = new Logs("INFO", System.currentTimeMillis() - currentTime.get());
        currentTime.remove();
        redisUtil.set("logs-info", getLog(log, joinPoint));
    }

    /**
     * 保存错误日志信息
     *
     * @param joinPoint
     * @param e
     */
    public void saveErrorLog(JoinPoint joinPoint, Throwable e) {
        currentTime.set(System.currentTimeMillis());
        Logs log = new Logs("ERROR", System.currentTimeMillis() - currentTime.get());
        currentTime.remove();
        log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes());
        redisUtil.set("logs-err", getLog(log, (ProceedingJoinPoint) joinPoint));
    }

    /**
     * 补充日志信息
     *
     * @param log
     * @param joinPoint
     *
     * @return 日志对象
     */
    @Transactional(rollbackFor = Exception.class)
    public Logs getLog(Logs log, ProceedingJoinPoint joinPoint) {
        String username = getUsername();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";

        StringBuilder params = new StringBuilder("{");
        //参数值
        Object[] argValues = joinPoint.getArgs();
        //参数名称
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        if (argValues != null) {
            for (int i = 0; i < argValues.length; i++) {
                params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);
            }
        }

        if (getUid() != null) {
            log.setUid(getUid());
        }
        assert log != null;
        log.setRequestIp(StringUtils.getIp(RequestHolder.getHttpServletRequest()));

        String loginPath = "login";
        if (loginPath.equals(signature.getName())) {
            try {
                assert argValues != null;
                username = new JSONObject(argValues[0]).get("username").toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //描述信息
        String description = "";
        Method method = signature.getMethod();
        if (method.isAnnotationPresent(RequestMapping.class)) {
            description = method.getAnnotation(RequestMapping.class).name();

        }
        if (method.isAnnotationPresent(GetMapping.class)) {
            description = method.getAnnotation(GetMapping.class).name();
        }
        if (method.isAnnotationPresent(PostMapping.class)) {
            description = method.getAnnotation(PostMapping.class).name();
        }
        if (method.isAnnotationPresent(PutMapping.class)) {
            description = method.getAnnotation(PutMapping.class).name();
        }
        if (method.isAnnotationPresent(DeleteMapping.class)) {
            description = method.getAnnotation(DeleteMapping.class).name();
        }
        log.setDescription(description);
        log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
        log.setMethod(methodName);
        log.setUsername(username);
        log.setParams(params.toString() + " }");
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.setCreateTime(ft.format(new Date()));
        log.setBrowser(getBrowser());
        return log;
    }
}
